/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef TURBO_TRANS_PROTOBUF_UTL_H
#define TURBO_TRANS_PROTOBUF_UTL_H

#include "google/protobuf/dynamic_message.h"
#include "google/protobuf/message.h"
#include "google/protobuf/descriptor.pb.h"
#include "google/protobuf/descriptor_lite.h"
#include "napi/native_api.h"

namespace protobuf_util {

struct JsToMessageContext {
  const napi_env env;
  const google::protobuf::Message *msg;
  google::protobuf::FieldDescriptor *field;
  const napi_value value;
  bool is_repeated = false;
    
//   JsToMessageContext(napi_env env, google::protobuf::Message *msg, napi_value value)
//       : env(env), msg(msg), value(value) {}
};

/**
 * 转换类
 */
class ConverterSingleton {

  private:
  ConverterSingleton() = default;

  ~ConverterSingleton() = default;

  ConverterSingleton(const ConverterSingleton &) = delete;
  ConverterSingleton &operator=(const ConverterSingleton &) = delete;
  /**
   * js to message function
   */
  using JsToMessageFunction = std::function<bool(const napi_env, google::protobuf::Message *,
                                                 const google::protobuf::FieldDescriptor *, napi_value, bool)>;
  // key=>Type ,value 转换方法
  std::map<google::protobuf::internal::FieldDescriptorLite::Type, JsToMessageFunction> jsToMessageFunctionMap;

  public:
  static ConverterSingleton &getInstance();
  /**
   * JS转换为Message
   * @param napi_env
   * @param napi_value JS value
   * @param Message
   * @return bool
   */
  bool JsToMessage(napi_env, napi_value, google::protobuf::Message *);
  /**
   * Message转换为JS
   * @param napi_env
   * @param napi_value JS value
   * @param Message
   * @return bool
   */
  bool MessageToJs(napi_env, google::protobuf::Message *, napi_value);
  /**
   * js类型转换为message类型，比如在pb中定义的是var关键字，在ets中生成的结果是PB_var,需要将PB_var的值赋值给var,输入是PB_var，输出是var
   * @param propertyName
   * @return
   */
  std::string PropertyToMessage(std::string propertyName);

  /**
   * message类型转换为js，比如在pb中定义的是var关键字，在ets中生成的结果是PB_var,需要将var的值赋值给PB_var,输入是var，输出是PB_var
   * @param propertyName
   * @return
   */
  std::string PropertyToJs(std::string propertyName);
  /**
   * 获取map
   * @return
   */
  std::map<google::protobuf::internal::FieldDescriptorLite::Type, JsToMessageFunction>& getJsToMessageFunctionMap() {
    return jsToMessageFunctionMap;
  }
};


class DynamicMessageFactorySingleton {
public:
    DynamicMessageFactorySingleton(const DynamicMessageFactorySingleton&) = delete;
    DynamicMessageFactorySingleton& operator=(const DynamicMessageFactorySingleton&) = delete;

    static google::protobuf::DynamicMessageFactory* GetInstance() {
        static google::protobuf::DynamicMessageFactory instance;
        return &instance;
    }

private:
    DynamicMessageFactorySingleton() = default;
};



/**
 *
 * @param
 * @return
 */
bool addDescToPool(const google::protobuf::FileDescriptorProto &);
/**
 *
 * @return DescriptorPool
 */
google::protobuf::DescriptorPool &getGlobalDescPool();
} // namespace protobuf_util

#endif // TURBO_TRANS_PROTOBUF_UTL_H
